home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SNNSV32.ZIP / SNNSv3.2 / kernel / sources / rcc_learn.c < prev    next >
C/C++ Source or Header  |  1994-04-25  |  57KB  |  1,869 lines

  1. /*****************************************************************************
  2.   FILE           : rcc_learn.c
  3.   SHORTNAME      : 
  4.   SNNS VERSION   : 3.2
  5.  
  6.   PURPOSE        : Functions of RCC
  7.   NOTES          :
  8.  
  9.   AUTHOR         : Michael Schmalzl
  10.   DATE           : 5.2.92
  11.  
  12.   CHANGED BY     : Guenter Mamier
  13.   IDENTIFICATION : @(#)rcc_learn.c    1.12 4/7/94
  14.   SCCS VERSION   : 1.12
  15.   LAST CHANGE    : 4/7/94
  16.  
  17.              Copyright (c) 1990-1994  SNNS Group, IPVR, Univ. Stuttgart, FRG
  18.  
  19. ******************************************************************************/
  20.  
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include <time.h>  
  24. #include <memory.h>
  25. #include <malloc.h>
  26. #include <values.h>
  27.  
  28. #include "kr_typ.h"      /*  Kernel Types and Constants  */
  29. #include "kr_const.h"    /*  Constant Declarators for SNNS-Kernel  */
  30. #include "kr_def.h"      /*  Default Values  */
  31. #include "kernel.h"      /*  kernel function prototypes  */
  32. #include "kr_mac.h"      /*  Kernel Macros   */
  33. #include "random.h"
  34.  
  35. #include "kr_ui.h"
  36. #include "cc_type.h"
  37. #include "cc_mac.h"
  38. #include "rcc_learn.ph"
  39. #include "cc_rcc.h"
  40. #include "kr_newpattern.h"
  41.  
  42.  
  43. /*****************************************************************************
  44.   FUNCTION : rcc_searchRecurrentLinks
  45.  
  46.   PURPOSE  : Searches for recurrent links.
  47.   NOTES    :
  48.  
  49.   UPDATE   : 5.2.93
  50. ******************************************************************************/
  51. krui_err rcc_searchRecurrentLinks(void)
  52. {
  53.     int CurrentUnit;
  54.     struct Unit *unit_ptr;
  55.     float linkValue;
  56.  
  57.     FOR_ALL_UNITS(unit_ptr){
  58.     if(IS_HIDDEN_UNIT(unit_ptr)){
  59.         KernelErrorCode = 
  60.         krui_setCurrentUnit(CurrentUnit = GET_UNIT_NO(unit_ptr)); 
  61.         ERROR_CHECK;
  62.         if(kr_isConnected(CurrentUnit,&linkValue)) {
  63.  
  64.         /* delete recurrent link */
  65.         KernelErrorCode = krui_deleteLink(); 
  66.         ERROR_CHECK;
  67.  
  68.         /* generate recurent link */
  69.         KernelErrorCode = krui_createLink(CurrentUnit,linkValue); 
  70.         ERROR_CHECK;
  71.         }
  72.     }
  73.     }
  74.     return(KRERR_NO_ERROR);
  75. }
  76.  
  77.  
  78.  
  79. /*****************************************************************************
  80.   FUNCTION : rcc_test
  81.  
  82.   PURPOSE  : Tests wether to continue learning or not.
  83.   NOTES    :
  84.  
  85.   UPDATE   : 5.2.93
  86. ******************************************************************************/
  87. static int rcc_test(int StartPattern, int EndPattern, float maxPixelError)
  88. {
  89.     int p,o,pat,sub;
  90.     int start, end;
  91.     Patterns out_pat;
  92.     struct Unit *unitPtr;
  93.  
  94.  
  95.     /* compute the necessary sub patterns */
  96.  
  97.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  98.     if(KernelErrorCode != KRERR_NO_ERROR)
  99.         return (KernelErrorCode);
  100.  
  101.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  102.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  103.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  104.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  105.     for(p=start; p<=end;p++){
  106.     kr_getSubPatternByNo(&pat,&sub,p);
  107.     rcc_propagateNetForward(pat,sub);
  108.  
  109.     out_pat = kr_getSubPatData(pat,sub,OUTPUT,NULL);
  110.     FOR_ALL_OUTPUT_UNITS(unitPtr,o){
  111.         if((fabs(*(out_pat++) - unitPtr->Out.output))>maxPixelError){
  112.         return(CONTINUE_LEARNING);
  113.         } 
  114.     }
  115.     }
  116.     return(STOP_LEARNING);
  117. }
  118.  
  119.  
  120.  
  121. /*****************************************************************************
  122.   FUNCTION : rcc_propagateNetForward
  123.  
  124.   PURPOSE  : Propagates a pattern forward through the net.
  125.   NOTES    :
  126.  
  127.   UPDATE   : 5.2.93
  128. ******************************************************************************/
  129. static void rcc_propagateNetForward(int PatternNo, int sub_pat_no)
  130. {
  131.     register struct Unit  *inputUnitPtr,*outputUnitPtr,*hiddenUnitPtr;
  132.     register Patterns  in_pat;
  133.     register int dummy;
  134.  
  135.     in_pat = kr_getSubPatData(PatternNo,sub_pat_no,INPUT,NULL);
  136.  
  137.     FOR_ALL_INPUT_UNITS(inputUnitPtr,dummy){
  138.     if(inputUnitPtr->out_func == OUT_IDENTITY) {
  139.         inputUnitPtr->Out.output = inputUnitPtr->act = *in_pat++;
  140.     }else{
  141.         inputUnitPtr->Out.output = 
  142.         (*inputUnitPtr->out_func) (inputUnitPtr->act = *in_pat++);
  143.     }
  144.     }
  145.  
  146.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,dummy) {
  147.     hiddenUnitPtr->lln = reset[PatternNo];
  148.     hiddenUnitPtr->act = (*hiddenUnitPtr->act_func)(hiddenUnitPtr);
  149.     if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  150.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  151.     }else{
  152.         hiddenUnitPtr->Out.output = 
  153.         (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  154.     }
  155.     }
  156.  
  157.     FOR_ALL_OUTPUT_UNITS(outputUnitPtr,dummy) {
  158.     outputUnitPtr->lln = reset[PatternNo];
  159.     outputUnitPtr->act = (*outputUnitPtr->act_func) (outputUnitPtr);
  160.     if(outputUnitPtr->out_func == OUT_IDENTITY) {
  161.         outputUnitPtr->Out.output = outputUnitPtr->act;
  162.     }else{
  163.         outputUnitPtr->Out.output = 
  164.         (*outputUnitPtr->out_func) (outputUnitPtr->act);
  165.     }
  166.     }
  167. }
  168.  
  169.  
  170.  
  171. /*****************************************************************************
  172.   FUNCTION : rcc_calculateOutputUnitError
  173.  
  174.   PURPOSE  : Calculates the error of the output units and stores it in the
  175.              array OutputUnitError.
  176.   NOTES    :
  177.  
  178.   UPDATE   : 5.2.93
  179. ******************************************************************************/
  180. static void rcc_calculateOutputUnitError(int StartPattern, int EndPattern)
  181. {
  182.     register struct Unit  *inputUnitPtr,*outputUnitPtr,*hiddenUnitPtr;
  183.     register Patterns  in_pat,out_pat;
  184.     register int dummy,o,p;
  185.     int start, end;
  186.     int pat, sub;
  187.  
  188.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  189.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  190.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  191.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  192.     for(p=start; p<=end;p++){
  193.  
  194.     kr_getSubPatternByNo(&pat,&sub,p);
  195.     in_pat = kr_getSubPatData(pat,sub,INPUT,NULL);
  196.     out_pat = kr_getSubPatData(pat,sub,OUTPUT,NULL);
  197.  
  198.     FOR_ALL_INPUT_UNITS(inputUnitPtr,dummy){
  199.         if(inputUnitPtr->out_func == OUT_IDENTITY) {
  200.         inputUnitPtr->Out.output = inputUnitPtr->act = *in_pat++;
  201.         }else{
  202.         inputUnitPtr->Out.output = 
  203.             (*inputUnitPtr->out_func) (inputUnitPtr->act = *in_pat++);
  204.         }
  205.     }
  206.  
  207.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,dummy) {
  208.         hiddenUnitPtr->lln = reset[p];
  209.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func) (hiddenUnitPtr);
  210.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  211.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  212.         }else{
  213.         hiddenUnitPtr->Out.output = 
  214.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  215.         }
  216.     }
  217.     
  218.     FOR_ALL_OUTPUT_UNITS(outputUnitPtr,o) {
  219.         outputUnitPtr->lln = reset[p];
  220.         outputUnitPtr->act = (*outputUnitPtr->act_func)(outputUnitPtr);
  221.         if(outputUnitPtr->out_func == OUT_IDENTITY) {
  222.         outputUnitPtr->Out.output = outputUnitPtr->act;
  223.         }else{
  224.         outputUnitPtr->Out.output = 
  225.             (*outputUnitPtr->out_func) (outputUnitPtr->act);
  226.         }
  227.         OutputUnitSumError[o] += 
  228.         (OutputUnitError[p][o] =  
  229.                (outputUnitPtr->Out.output-(*out_pat++))*
  230.                ((*outputUnitPtr->act_deriv_func)(outputUnitPtr)+0.1)); 
  231.     } 
  232.     } 
  233. }
  234.  
  235.  
  236.  
  237. /*****************************************************************************
  238.   FUNCTION : rcc_calculateSpecialUnitActivation
  239.  
  240.   PURPOSE  : Calculates covariance between the special units and the output
  241.              units and stores it in the array CorBetweenSpecialActAndOutError.
  242.   NOTES    :
  243.  
  244.   UPDATE   : 5.2.93
  245. ******************************************************************************/
  246. static void rcc_calculateSpecialUnitActivation(int StartPattern, int EndPattern)
  247. {
  248.     register struct Unit  *inputUnitPtr,*specialUnitPtr,*outputUnitPtr,*hiddenUnitPtr;
  249.     register Patterns  in_pat;
  250.     register int dummy,o,s,p;
  251.     int pat,sub;
  252.     int start,end;
  253.   
  254.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  255.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  256.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  257.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  258.     for(p=start; p<=end;p++){
  259.  
  260.     kr_getSubPatternByNo(&pat,&sub,p);
  261.     in_pat = kr_getSubPatData(pat,sub,INPUT,NULL);
  262.  
  263.     FOR_ALL_INPUT_UNITS(inputUnitPtr,dummy){
  264.         if(inputUnitPtr->out_func == OUT_IDENTITY) {
  265.         inputUnitPtr->Out.output = inputUnitPtr->act = *in_pat++;
  266.         }else{
  267.         inputUnitPtr->Out.output = 
  268.             (*inputUnitPtr->out_func) (inputUnitPtr->act = *in_pat++);
  269.         }
  270.     }
  271.  
  272.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,dummy) {
  273.         hiddenUnitPtr->lln = reset[p];
  274.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func) (hiddenUnitPtr);
  275.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  276.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  277.         }else{
  278.         hiddenUnitPtr->Out.output = 
  279.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  280.         }
  281.     }
  282.     
  283.     FOR_ALL_SPECIAL_UNITS(specialUnitPtr,s) {
  284.         specialUnitPtr->lln = reset[p];
  285.         specialUnitPtr->act = (*specialUnitPtr->act_func) (specialUnitPtr);
  286.         if(specialUnitPtr->out_func == OUT_IDENTITY) {
  287.         specialUnitPtr->Out.output = specialUnitPtr->act;
  288.         }else{
  289.         specialUnitPtr->Out.output = 
  290.             (*specialUnitPtr->out_func) (specialUnitPtr->act);
  291.         }
  292.         SpecialUnitSumAct[s] += 
  293.         SpecialUnitAct[p][s] = 
  294.             specialUnitPtr->Out.output;
  295.     }
  296.     } 
  297.   
  298.     for(p=start; p<=end;p++){
  299.     FOR_ALL_SPECIAL_UNITS(specialUnitPtr,s) {
  300.         FOR_ALL_OUTPUT_UNITS(outputUnitPtr,o) {
  301.         CorBetweenSpecialActAndOutError[s][o] += 
  302.             SpecialUnitAct[p][s] * OutputUnitError[p][o];
  303.         }
  304.     }
  305.     }    
  306. }
  307.  
  308.  
  309.  
  310. /************* begin rprop routines *********************/
  311.  
  312.  
  313. /*****************************************************************************
  314.   FUNCTION : rcc_RPO_trainNet
  315.  
  316.   PURPOSE  : Minimize the error of the output units.
  317.   NOTES    :
  318.  
  319.   UPDATE   : 5.2.93
  320. ******************************************************************************/
  321. static void rcc_RPO_trainNet(int maxNoOfErrorUpdateCycles, float minErrorChange,
  322.                              int outPatience,int StartPattern, int EndPattern, 
  323.                  float epsilonMinus, float epsilonPlus, float dummy, 
  324.                  float **ParameterOutArray, int *NoOfOutParams)
  325. {
  326.     int m,p,counter=0;
  327.     int sub, pat;
  328.     int start, end;
  329.     float oldNetError;
  330.     static float OutParameter[1];
  331.  
  332.     *NoOfOutParams = 1;
  333.     *ParameterOutArray = OutParameter;
  334.  
  335.  
  336.     SumSqError = 0.0;
  337.     cc_initOutputUnits();
  338.  
  339.     /* compute the necessary sub patterns */
  340.  
  341.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  342.     if(KernelErrorCode != KRERR_NO_ERROR)
  343.         return;
  344.  
  345.     /* give oldNetError a meaningful initial value */
  346.     NET_ERROR(OutParameter)=FLOAT_MAX;
  347.     do {
  348.     oldNetError = NET_ERROR(OutParameter);
  349.     for(m=0;m<outPatience;m++) {
  350.         NET_ERROR(OutParameter) = 0.0;
  351.         SumSqError = 0.0;
  352.         KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  353.         start = kr_AbsPosOfFirstSubPat(StartPattern);
  354.         end   = kr_AbsPosOfFirstSubPat(EndPattern);
  355.         end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  356.         for(p=start; p<=end;p++){
  357.         kr_getSubPatternByNo(&pat,&sub,p);
  358.         rcc_propagateNetForward(pat,sub);
  359.         NET_ERROR(OutParameter) +=rcc_RPO_propagateNetBackward(pat,sub);
  360.         }
  361.         rcc_RPO_updateNet(epsilonMinus,epsilonPlus,dummy);
  362.         if(cc_printOnOff) {
  363.         printf("Epoch: %d NetError: %f \n",++counter,
  364.                NET_ERROR(OutParameter));
  365.         } 
  366.         if((maxNoOfErrorUpdateCycles--) == 0) {
  367.         return;
  368.         }
  369.     }
  370.     } while(fabs(oldNetError-NET_ERROR(OutParameter)) >= 
  371.         (minErrorChange * oldNetError));
  372. }
  373.  
  374.  
  375.  
  376. /*****************************************************************************
  377.   FUNCTION : rcc_RPO_propagateNetBackward
  378.  
  379.   PURPOSE  : Calculate the error of the output units.
  380.   NOTES    :
  381.  
  382.   UPDATE   : 5.2.93
  383. ******************************************************************************/
  384. static  float rcc_RPO_propagateNetBackward(int PatternNo, int sub_pat_no)
  385. {
  386.     struct Link   *LinkPtr;
  387.     struct Site   *site_ptr;
  388.     struct Unit   *OutputUnitPtr;
  389.     Patterns      out_pat;
  390.     float         error,sum_error,devit;
  391.     int dummy;
  392.  
  393.     sum_error = 0.0;    
  394.     out_pat = kr_getSubPatData(PatternNo,sub_pat_no,OUTPUT,NULL);
  395.  
  396.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
  397.     devit =  OutputUnitPtr->Out.output - *(out_pat++);
  398.  
  399.     sum_error += devit * devit;
  400.     error = devit * ((*OutputUnitPtr->act_deriv_func)(OutputUnitPtr) + 0.1);
  401.     SumSqError += error * error;
  402.  
  403.     BIAS_CURRENT_SLOPE(OutputUnitPtr) += error;
  404.  
  405.     if (UNIT_HAS_DIRECT_INPUTS(OutputUnitPtr)) {  
  406.         FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  407.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  408.         }
  409.     }else{
  410.         FOR_ALL_SITES_AND_LINKS(OutputUnitPtr,site_ptr,LinkPtr) {
  411.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  412.         }
  413.     }
  414.     }
  415.     return(sum_error); 
  416. }
  417.  
  418.  
  419.  
  420. /*****************************************************************************
  421.   FUNCTION : rcc_RPO_updateNet
  422.  
  423.   PURPOSE  : Update the weights of the output units with rprop.
  424.   NOTES    :
  425.  
  426.   UPDATE   : 5.2.93
  427. ******************************************************************************/
  428. static void rcc_RPO_updateNet(float epsilonMinus, float epsilonPlus, 
  429.                   float dummy)
  430. {
  431.     struct Unit *OutputUnitPtr;
  432.     struct Link *LinkPtr;
  433.     float bias_previousSlope,bias_currentSlope,bias_lastWeightChange,
  434.           bias_weightChange=0.0;
  435.     float ln_previousSlope,ln_currentSlope,ln_lastWeightChange,
  436.           ln_weightChange=0.0;
  437.     int o;
  438.  
  439.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  440.     bias_previousSlope    = BIAS_PREVIOUS_SLOPE(OutputUnitPtr);
  441.     bias_currentSlope     = BIAS_CURRENT_SLOPE(OutputUnitPtr);
  442.     bias_lastWeightChange = 
  443.         (BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr) == 0.0) ? 
  444.         (1.0) : (BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr));
  445.    
  446.     if(bias_currentSlope != 0.0) {
  447.         if(bias_previousSlope == 0.0) {
  448.         bias_weightChange = 
  449.             fabs(bias_lastWeightChange) * SIGN(bias_currentSlope);
  450.         }else if(bias_previousSlope > 0.0) {  
  451.         if(bias_currentSlope > 0.0) {
  452.             bias_weightChange = epsilonPlus * bias_lastWeightChange;  
  453.         }else if(bias_currentSlope < 0.0) {
  454.             bias_weightChange = -epsilonMinus * bias_lastWeightChange;
  455.         }
  456.         }else if(bias_previousSlope < 0.0) {
  457.         if(bias_currentSlope < 0.0) {
  458.             bias_weightChange = epsilonPlus * bias_lastWeightChange;
  459.         }else if(bias_currentSlope > 0.0) {
  460.             bias_weightChange = -epsilonMinus * bias_lastWeightChange;
  461.         }
  462.         }else{
  463.         bias_weightChange = 1.0 * SIGN(bias_currentSlope);
  464.         }
  465.  
  466.         if(fabs(bias_weightChange) < 0.00001) {
  467.         bias_weightChange = 0.00001 * SIGN(bias_weightChange);
  468.         }
  469.         if(fabs(bias_weightChange) > 10.0) {
  470.         bias_weightChange = 10.0 * SIGN(bias_weightChange);
  471.         }
  472.    
  473.         OutputUnitPtr->bias -= 
  474.         (BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr) = bias_weightChange); 
  475.         BIAS_PREVIOUS_SLOPE(OutputUnitPtr) = bias_currentSlope;
  476.         BIAS_CURRENT_SLOPE(OutputUnitPtr) = 0.0;
  477.     }
  478.  
  479.     FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  480.    
  481.         ln_previousSlope    = LN_PREVIOUS_SLOPE(LinkPtr);
  482.         ln_currentSlope     = LN_CURRENT_SLOPE(LinkPtr);
  483.         ln_lastWeightChange = 
  484.         (LN_LAST_WEIGHT_CHANGE(LinkPtr) == 0.0) ? 
  485.             (1.0) : (LN_LAST_WEIGHT_CHANGE(LinkPtr));
  486.  
  487.         if(ln_currentSlope != 0.0) {
  488.         if(ln_previousSlope == 0.0) {
  489.             ln_weightChange = 
  490.             fabs(ln_lastWeightChange) * SIGN(ln_currentSlope);
  491.         }
  492.         else if(ln_previousSlope > 0.0) {  
  493.             if(ln_currentSlope > 0.0) {
  494.             ln_weightChange = epsilonPlus * ln_lastWeightChange;  
  495.             }
  496.             else if(ln_currentSlope < 0.0) {
  497.             ln_weightChange = -epsilonMinus * ln_lastWeightChange;
  498.             }
  499.         }else if(ln_previousSlope < 0.0) {
  500.             if(ln_currentSlope < 0.0) {
  501.             ln_weightChange = epsilonPlus * ln_lastWeightChange;
  502.             }else if(ln_currentSlope > 0.0) {
  503.             ln_weightChange = -epsilonMinus * ln_lastWeightChange;
  504.             }
  505.         }else{
  506.             ln_weightChange = 1.0 * SIGN(ln_currentSlope);
  507.         }
  508.     
  509.         if(fabs(ln_weightChange) < 0.00001) {
  510.             ln_weightChange = 0.00001 * SIGN(ln_weightChange);
  511.         }
  512.         if(fabs(ln_weightChange) > 10) {
  513.             ln_weightChange = 10 * SIGN(ln_weightChange);
  514.         }
  515.  
  516.         LinkPtr->weight -= 
  517.             LN_LAST_WEIGHT_CHANGE(LinkPtr) = ln_weightChange; 
  518.         LN_PREVIOUS_SLOPE(LinkPtr)   = ln_currentSlope;
  519.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  520.         }
  521.     }
  522.     }
  523. }
  524.  
  525.  
  526. /*****************************************************************************
  527.   FUNCTION : rcc_RPS_trainNet
  528.  
  529.   PURPOSE  : Maximize the covariance of the special units.
  530.   NOTES    :
  531.  
  532.   UPDATE   : 5.2.93
  533. ******************************************************************************/
  534. static void rcc_RPS_trainNet(int maxNoOfCovarianceUpdateCycles, 
  535.                  float minCovarianceChange,int specialPatience, 
  536.                  int StartPattern, int EndPattern, 
  537.                  float epsilonMinus, float epsilonPlus, 
  538.                  float dummy, int MaxSpecialUnitNo)
  539. {
  540.     int m,counter=0;
  541.     float oldHighScore,newHighScore=0.0;
  542.  
  543.     cc_initErrorArrays();
  544.     rcc_calculateOutputUnitError(StartPattern,EndPattern);
  545.  
  546.     do {
  547.     oldHighScore = newHighScore;
  548.     for(m=0;m<specialPatience;m++) { 
  549.         counter++;
  550.         rcc_calculateSpecialUnitActivation(StartPattern,EndPattern);
  551.         newHighScore = 
  552.         rcc_RPS_propagateNetBackward(StartPattern,EndPattern,counter);
  553.         rcc_RPS_updateNet(epsilonMinus,epsilonPlus,dummy);
  554.         cc_initActivationArrays(); 
  555.         if((maxNoOfCovarianceUpdateCycles--) == 0) {
  556.         return;
  557.         }
  558.     }
  559.     } while(fabs(newHighScore-oldHighScore) >= 
  560.         (minCovarianceChange * oldHighScore));
  561. }
  562.  
  563.  
  564.  
  565. /*****************************************************************************
  566.   FUNCTION : rcc_RPS_propagateNetBackward
  567.  
  568.   PURPOSE  : Calculate the special unit with maximum covariance and return it.
  569.   NOTES    :
  570.  
  571.   UPDATE   : 5.2.93
  572. ******************************************************************************/
  573. static float rcc_RPS_propagateNetBackward(int StartPattern, int EndPattern, 
  574.                       int counter)
  575. {
  576.     float change=0.0,bestSpecialUnitScore,actPrime,recurrentLinkWeight,dsum;
  577.     int s,o,p,n,h;
  578.     struct Unit *SpecialUnitPtr,*OutputUnitPtr,*hiddenUnitPtr;
  579.     struct Link *LinkPtr,*recurrentLinkPtr;
  580.     int start, end;
  581.  
  582.  
  583.     bestSpecialUnitScore = 
  584.     cc_calculateCorrelation(StartPattern,EndPattern,counter); 
  585.  
  586.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  587.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  588.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  589.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  590.     n = end - start + 1;
  591.     for(p=start; p<=end;p++){
  592.  
  593.     cc_initInputUnitsWithPattern(p);
  594.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,h) { 
  595.         hiddenUnitPtr->lln = reset[p];
  596.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func)(hiddenUnitPtr);
  597.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  598.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  599.         }else{
  600.         hiddenUnitPtr->Out.output = 
  601.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  602.         }
  603.     }
  604.    
  605.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
  606.         change = 0.0;
  607.         SpecialUnitPtr->act = SpecialUnitAct[p][s];
  608.         actPrime = (*SpecialUnitPtr->act_deriv_func)(SpecialUnitPtr);
  609.         FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  610.         change -= CorBetweenSpecialActAndOutError[s][o] *
  611.             ((OutputUnitError[p][o] - OutputUnitSumError[o]/n)/
  612.              SumSqError);
  613.         }
  614.  
  615.         counter = 0;
  616.         GET_RECURRENT_LINK(SpecialUnitPtr,recurrentLinkPtr);
  617.         if(reset[p]) {
  618.         linkArray[s][counter] = 0.0;
  619.         }
  620.         recurrentLinkWeight = recurrentLinkPtr->weight; 
  621.         if(!reset[p]) {    /* calculate slope of the recurrent link */
  622.         dsum = actPrime * (SpecialUnitAct[p-1][s] + 
  623.                    (recurrentLinkWeight*linkArray[s][counter]));
  624.         LN_CURRENT_SLOPE(recurrentLinkPtr) += change * dsum;
  625.         linkArray[s][counter++] = dsum; 
  626.         }
  627.  
  628.         FOR_ALL_NOT_RECURRENT_LINKS(SpecialUnitPtr,LinkPtr) {
  629.         if(reset[p]) {
  630.             linkArray[s][counter] = 0.0;
  631.         }
  632.         dsum = actPrime * (LinkPtr->to->Out.output + 
  633.                    (recurrentLinkWeight*linkArray[s][counter]));
  634.         LN_CURRENT_SLOPE(LinkPtr) += change * dsum;
  635.         linkArray[s][counter++] = dsum;
  636.         }
  637.  
  638.         if(reset[p]) {
  639.         linkArray[s][counter] = 0.0;
  640.         }
  641.         dsum = actPrime * (1 + (recurrentLinkWeight*linkArray[s][counter]));
  642.         BIAS_CURRENT_SLOPE(SpecialUnitPtr) += change * dsum;
  643.         linkArray[s][counter] = dsum;
  644.     }
  645.     }
  646.     return(bestSpecialUnitScore);
  647. }
  648.  
  649.  
  650.  
  651. /*****************************************************************************
  652.   FUNCTION : rcc_RPS_updateNet
  653.  
  654.   PURPOSE  : Update the weights of the special units with rprop.
  655.   NOTES    :
  656.  
  657.   UPDATE   : 5.2.93
  658. ******************************************************************************/
  659. static void rcc_RPS_updateNet(float epsilonMinus,float epsilonPlus, float dummy)
  660. {
  661.     struct Unit *specialUnitPtr;
  662.     struct Link *LinkPtr;
  663.     float bias_previousSlope,bias_currentSlope,bias_lastWeightChange,
  664.           bias_weightChange=0.0;
  665.     float ln_previousSlope,ln_currentSlope,ln_lastWeightChange,
  666.           ln_weightChange=0.0;
  667.     int s;
  668.  
  669.     FOR_ALL_SPECIAL_UNITS(specialUnitPtr,s) {
  670.     bias_previousSlope    = BIAS_PREVIOUS_SLOPE(specialUnitPtr);
  671.     bias_currentSlope     = BIAS_CURRENT_SLOPE(specialUnitPtr);
  672.     bias_lastWeightChange = 
  673.         (BIAS_LAST_WEIGHT_CHANGE(specialUnitPtr) == 0.0) ? 
  674.         (1.0) : (BIAS_LAST_WEIGHT_CHANGE(specialUnitPtr));
  675.    
  676.     if(bias_currentSlope != 0.0) {
  677.         if(bias_previousSlope == 0.0) {
  678.         bias_weightChange = 
  679.             fabs(bias_lastWeightChange) * SIGN(bias_currentSlope);
  680.         }else if(bias_previousSlope > 0.0) {  
  681.         if(bias_currentSlope > 0.0) {
  682.             bias_weightChange = epsilonPlus * bias_lastWeightChange;  
  683.         }else if(bias_currentSlope < 0.0) {
  684.             bias_weightChange = -epsilonMinus * bias_lastWeightChange;
  685.         }
  686.         }else if(bias_previousSlope < 0.0) {
  687.         if(bias_currentSlope < 0.0) {
  688.             bias_weightChange = epsilonPlus * bias_lastWeightChange;
  689.         }else if(bias_currentSlope > 0.0) {
  690.             bias_weightChange = -epsilonMinus * bias_lastWeightChange;
  691.         }
  692.         }else {
  693.         bias_weightChange = 1.0 * SIGN(bias_currentSlope);
  694.         }
  695.  
  696.         if(fabs(bias_weightChange) < 0.00001) {
  697.         bias_weightChange = 0.00001 * SIGN(bias_weightChange);
  698.         }
  699.         if(fabs(bias_weightChange) > 10.0) {
  700.         bias_weightChange = 10.0 * SIGN(bias_weightChange);
  701.         }
  702.   
  703.         specialUnitPtr->bias -= 
  704.         (BIAS_LAST_WEIGHT_CHANGE(specialUnitPtr) = bias_weightChange); 
  705.         BIAS_PREVIOUS_SLOPE(specialUnitPtr) = bias_currentSlope;
  706.         BIAS_CURRENT_SLOPE(specialUnitPtr) = 0.0;
  707.     }
  708.  
  709.     FOR_ALL_LINKS(specialUnitPtr,LinkPtr) {
  710.    
  711.         ln_previousSlope    = LN_PREVIOUS_SLOPE(LinkPtr);
  712.         ln_currentSlope     = LN_CURRENT_SLOPE(LinkPtr);
  713.         ln_lastWeightChange = 
  714.         (LN_LAST_WEIGHT_CHANGE(LinkPtr) == 0.0) ? 
  715.             (1.0) : (LN_LAST_WEIGHT_CHANGE(LinkPtr));
  716.  
  717.         if(ln_currentSlope != 0.0) {
  718.         if(ln_previousSlope == 0.0) {
  719.             ln_weightChange = 
  720.             fabs(ln_lastWeightChange) * SIGN(ln_currentSlope);
  721.         }else if(ln_previousSlope > 0.0) {  
  722.             if(ln_currentSlope > 0.0) {
  723.             ln_weightChange = epsilonPlus * ln_lastWeightChange;  
  724.             }else if(ln_currentSlope < 0.0) {
  725.             ln_weightChange = -epsilonMinus * ln_lastWeightChange;
  726.             }
  727.         }else if(ln_previousSlope < 0.0) {
  728.             if(ln_currentSlope < 0.0) {
  729.             ln_weightChange = epsilonPlus * ln_lastWeightChange;
  730.             }else if(ln_currentSlope > 0.0) {
  731.             ln_weightChange = -epsilonMinus * ln_lastWeightChange;
  732.             }
  733.         }else {
  734.             ln_weightChange = 1.0 * SIGN(ln_currentSlope);
  735.         }
  736.     
  737.         if(fabs(ln_weightChange) < 0.00001) {
  738.             ln_weightChange = 0.00001 * SIGN(ln_weightChange);
  739.         }
  740.         if(fabs(ln_weightChange) > 10) {
  741.             ln_weightChange = 10 * SIGN(ln_weightChange);
  742.         }
  743.  
  744.         LinkPtr->weight -= 
  745.             LN_LAST_WEIGHT_CHANGE(LinkPtr) = ln_weightChange; 
  746.         LN_PREVIOUS_SLOPE(LinkPtr)   = ln_currentSlope;
  747.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  748.         }
  749.     }
  750.     }
  751. }
  752. /************* end rprop routines *********************/
  753.  
  754.  
  755.  
  756. /************* begin quickprop routines *********************/
  757.  
  758. /*****************************************************************************
  759.   FUNCTION : rcc_QPO_trainNet
  760.  
  761.   PURPOSE  : Minimize the error of the output units.
  762.   NOTES    :
  763.  
  764.   UPDATE   : 5.2.93
  765. ******************************************************************************/
  766. static void rcc_QPO_trainNet(int maxNoOfErrorUpdateCycles, float minErrorChange,
  767.                              int outPatience, int StartPattern, int EndPattern, 
  768.                  float epsilon, float mu,float decay, 
  769.                  float **ParameterOutArray,int *NoOfOutParams)
  770. {
  771.     int m,p,pat,sub,counter=0;
  772.     float oldNetError;
  773.     static float OutParameter[1];
  774.     int start, end;
  775.  
  776.     *NoOfOutParams = 1;
  777.     *ParameterOutArray = OutParameter;
  778.  
  779.     SumSqError = 0.0;
  780.     cc_initOutputUnits();
  781.  
  782.     /* compute the necessary sub patterns */
  783.  
  784.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  785.     if(KernelErrorCode != KRERR_NO_ERROR)
  786.         return;
  787.  
  788.     /* give oldNetError a meaningful initial value */
  789.  
  790.     NET_ERROR(OutParameter)=FLOAT_MAX;
  791.     do {
  792.     oldNetError = NET_ERROR(OutParameter);
  793.     for(m=0;m<outPatience;m++) {
  794.         NET_ERROR(OutParameter) = 0.0;
  795.         SumSqError = 0.0;
  796.         KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  797.         start = kr_AbsPosOfFirstSubPat(StartPattern);
  798.         end   = kr_AbsPosOfFirstSubPat(EndPattern);
  799.         end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  800.         for(p=start; p<=end;p++){
  801.         kr_getSubPatternByNo(&pat,&sub,p);
  802.         rcc_propagateNetForward(pat,sub);
  803.         NET_ERROR(OutParameter) +=rcc_QPO_propagateNetBackward(pat,sub);
  804.         }
  805.         rcc_QPO_updateNet(epsilon,mu,decay);
  806.         if(cc_printOnOff) {
  807.         printf("Epoch: %d NetError: %f \n",++counter,
  808.                NET_ERROR(OutParameter));
  809.         }
  810.         if((maxNoOfErrorUpdateCycles--) == 0) {
  811.         return;
  812.         }
  813.     }
  814.     } while(fabs(oldNetError-NET_ERROR(OutParameter)) >= 
  815.         (minErrorChange * oldNetError));
  816. }
  817.  
  818.  
  819.  
  820. /*****************************************************************************
  821.   FUNCTION : rcc_QPO_propagateNetBackward
  822.  
  823.   PURPOSE  : Calculate the error of the output units.
  824.   NOTES    :
  825.  
  826.   UPDATE   : 5.2.93
  827. ******************************************************************************/
  828. static  float rcc_QPO_propagateNetBackward(int PatternNo, int sub_pat_no)
  829. {
  830.     struct Link   *LinkPtr;
  831.     struct Site   *site_ptr;
  832.     struct Unit   *OutputUnitPtr;
  833.     Patterns      out_pat;
  834.     float         error,sum_error,devit;
  835.     int dummy;
  836.  
  837.     sum_error = 0.0;    
  838.     out_pat = kr_getSubPatData(PatternNo,sub_pat_no,OUTPUT,NULL);
  839.  
  840.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
  841.     devit =  OutputUnitPtr->Out.output - *(out_pat++);
  842.  
  843.     sum_error += devit * devit;
  844.     error = devit * ((*OutputUnitPtr->act_deriv_func)(OutputUnitPtr) + 0.1);
  845.     SumSqError += error * error;
  846.  
  847.     BIAS_CURRENT_SLOPE(OutputUnitPtr) += error;
  848.  
  849.     if (UNIT_HAS_DIRECT_INPUTS(OutputUnitPtr)) {  
  850.         FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  851.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  852.         }
  853.     }else {
  854.         FOR_ALL_SITES_AND_LINKS(OutputUnitPtr,site_ptr,LinkPtr) {
  855.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  856.         }
  857.     }
  858.     }
  859.     return(sum_error); 
  860. }
  861.  
  862.  
  863.  
  864. /*****************************************************************************
  865.   FUNCTION : rcc_QPO_updateNet
  866.  
  867.   PURPOSE  : Update the weights of the output units with quickprop.
  868.   NOTES    :
  869.  
  870.   UPDATE   : 5.2.93
  871. ******************************************************************************/
  872. static void rcc_QPO_updateNet(float epsilon, float mu, float decay)
  873. {
  874.     struct Unit *OutputUnitPtr;
  875.     struct Link *LinkPtr;
  876.     float shrinkFactor=mu/(mu+1);
  877.     float bias_previousSlope,bias_currentSlope,bias_lastWeightChange,
  878.           bias_weightChange;
  879.     float ln_previousSlope,ln_currentSlope,ln_lastWeightChange,
  880.           ln_weightChange;
  881.     int o;
  882.  
  883.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  884.     bias_previousSlope = BIAS_PREVIOUS_SLOPE(OutputUnitPtr);
  885.     bias_currentSlope = 
  886.         BIAS_CURRENT_SLOPE(OutputUnitPtr) + decay * OutputUnitPtr->bias;
  887.     bias_lastWeightChange = BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr);
  888.  
  889.     bias_weightChange = 0.0;
  890.  
  891.     if(bias_previousSlope > 0.0) {
  892.         if(bias_currentSlope > 0.0) {
  893.         bias_weightChange -= epsilon * bias_currentSlope;
  894.         }
  895.         if(bias_currentSlope >= (shrinkFactor * bias_previousSlope)) {
  896.         bias_weightChange += mu * bias_lastWeightChange;
  897.         }else {
  898.         bias_weightChange += (bias_lastWeightChange*bias_currentSlope)/ 
  899.             (bias_previousSlope - bias_currentSlope); 
  900.         }
  901.     }else if(bias_previousSlope < 0.0) {
  902.         if(bias_currentSlope < 0.0) {
  903.         bias_weightChange -= epsilon * bias_currentSlope;
  904.         }
  905.         if(bias_currentSlope <= (shrinkFactor * bias_previousSlope)) {
  906.         bias_weightChange += mu * bias_lastWeightChange;
  907.         }else {
  908.         bias_weightChange += (bias_lastWeightChange*bias_currentSlope)/ 
  909.             (bias_previousSlope - bias_currentSlope); 
  910.         }
  911.     }else {
  912.         bias_weightChange -= epsilon * bias_currentSlope;
  913.     }
  914.     OutputUnitPtr->bias += 
  915.         (BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr) = bias_weightChange); 
  916.     BIAS_PREVIOUS_SLOPE(OutputUnitPtr) = bias_currentSlope;
  917.     BIAS_CURRENT_SLOPE(OutputUnitPtr) = 0.0;
  918.  
  919.     FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  920.    
  921.         ln_weightChange = 0.0;
  922.         ln_previousSlope = LN_PREVIOUS_SLOPE(LinkPtr);
  923.         ln_currentSlope = LN_CURRENT_SLOPE(LinkPtr) + decay*LinkPtr->weight;
  924.         ln_lastWeightChange = LN_LAST_WEIGHT_CHANGE(LinkPtr);
  925.    
  926.         if(ln_previousSlope > 0.0) {
  927.         if(ln_currentSlope > 0.0) {
  928.             ln_weightChange -= epsilon * ln_currentSlope;
  929.         }
  930.         if(ln_currentSlope >= (shrinkFactor * ln_previousSlope)) {
  931.             ln_weightChange += mu * ln_lastWeightChange;
  932.         }else {
  933.             ln_weightChange += (ln_lastWeightChange * ln_currentSlope) / 
  934.             (ln_previousSlope - ln_currentSlope); 
  935.         }
  936.         }else if(ln_previousSlope < 0.0) {
  937.         if(ln_currentSlope < 0.0) {
  938.             ln_weightChange -= epsilon * ln_currentSlope;
  939.         }
  940.         if(ln_currentSlope <= (shrinkFactor * ln_previousSlope)) {
  941.             ln_weightChange += mu * ln_lastWeightChange;
  942.         }else {
  943.             ln_weightChange += (ln_lastWeightChange*ln_currentSlope) / 
  944.             (ln_previousSlope - ln_currentSlope); 
  945.         }
  946.         }else {
  947.         ln_weightChange -= epsilon * ln_currentSlope;
  948.         }
  949.    
  950.         LinkPtr->weight += 
  951.         LN_LAST_WEIGHT_CHANGE(LinkPtr) = 
  952.             ln_weightChange; 
  953.         LN_PREVIOUS_SLOPE(LinkPtr)   = ln_currentSlope;
  954.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  955.     }
  956.     }
  957. }
  958.  
  959.  
  960.  
  961. /*****************************************************************************
  962.   FUNCTION : rcc_QPS_trainNet
  963.  
  964.   PURPOSE  : Maximize the covariance between the special units and the
  965.              output units.
  966.   NOTES    :
  967.  
  968.   UPDATE   : 5.2.93
  969. ******************************************************************************/
  970. static void rcc_QPS_trainNet(int maxNoOfCovarianceUpdateCycles, 
  971.                  float minCovarianceChange, int specialPatience, 
  972.                  int StartPattern, int EndPattern,
  973.                  float epsilon, float mu, float decay, 
  974.                  int MaxSpecialUnitNo)
  975. {
  976.     int m,counter=0;
  977.     float oldHighScore,newHighScore=0.0;
  978.  
  979.     cc_initErrorArrays();
  980.     rcc_calculateOutputUnitError(StartPattern,EndPattern);
  981.  
  982.     do {
  983.     oldHighScore = newHighScore;
  984.     for(m=0;m<specialPatience;m++) { 
  985.         counter++;
  986.         rcc_calculateSpecialUnitActivation(StartPattern,EndPattern);
  987.         newHighScore = 
  988.         rcc_QPS_propagateNetBackward(StartPattern,EndPattern,counter);
  989.         rcc_QPS_updateNet(epsilon,mu,decay);
  990.         cc_initActivationArrays(); 
  991.         if((maxNoOfCovarianceUpdateCycles--) == 0) {
  992.         return;
  993.         }
  994.     }
  995.     } while(fabs(newHighScore-oldHighScore) >= 
  996.         (minCovarianceChange * oldHighScore));
  997. }
  998.  
  999.  
  1000.  
  1001. /*****************************************************************************
  1002.   FUNCTION : rcc_QPS_propagateNetBackward
  1003.  
  1004.   PURPOSE  : Calculate the special unit with the maximum covariance and return 
  1005.              it.
  1006.   NOTES    :
  1007.  
  1008.   UPDATE   : 5.2.93
  1009. ******************************************************************************/
  1010. static float rcc_QPS_propagateNetBackward(int StartPattern, int EndPattern, 
  1011.                       int counter)
  1012. {
  1013.     float change=0.0,bestSpecialUnitScore,actPrime,recurrentLinkWeight,dsum;
  1014.     int s,o,p,n,h;
  1015.     int start, end;
  1016.     struct Unit *SpecialUnitPtr,*OutputUnitPtr,*hiddenUnitPtr;
  1017.     struct Link *LinkPtr,*recurrentLinkPtr;
  1018.  
  1019.  
  1020.     bestSpecialUnitScore = 
  1021.     cc_calculateCorrelation(StartPattern,EndPattern,counter); 
  1022.  
  1023.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  1024.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  1025.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  1026.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  1027.     n = end - start + 1;
  1028.     for(p=start; p<=end;p++){
  1029.  
  1030.     cc_initInputUnitsWithPattern(p);
  1031.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,h) { 
  1032.         hiddenUnitPtr->lln = reset[p];
  1033.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func)(hiddenUnitPtr);
  1034.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  1035.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  1036.         }else {
  1037.         hiddenUnitPtr->Out.output = 
  1038.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  1039.         }
  1040.     }
  1041.    
  1042.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
  1043.         change = 0.0;
  1044.         SpecialUnitPtr->act = SpecialUnitAct[p][s];
  1045.         actPrime = (*SpecialUnitPtr->act_deriv_func)(SpecialUnitPtr);
  1046.         FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  1047.         change -= CorBetweenSpecialActAndOutError[s][o] *
  1048.             ((OutputUnitError[p][o] - OutputUnitSumError[o]/n)/
  1049.              SumSqError);
  1050.         }
  1051.  
  1052.         counter = 0;
  1053.         GET_RECURRENT_LINK(SpecialUnitPtr,recurrentLinkPtr);
  1054.         if(reset[p]) {
  1055.         linkArray[s][counter] = 0.0;
  1056.         }
  1057.         recurrentLinkWeight = recurrentLinkPtr->weight; 
  1058.         if(!reset[p]) {    /* calculate slope of the recurrent link */
  1059.         dsum = actPrime * (SpecialUnitAct[p-1][s] + 
  1060.                    (recurrentLinkWeight*linkArray[s][counter]));
  1061.         LN_CURRENT_SLOPE(recurrentLinkPtr) += change * dsum;
  1062.         linkArray[s][counter++] = dsum; 
  1063.         }
  1064.  
  1065.         FOR_ALL_NOT_RECURRENT_LINKS(SpecialUnitPtr,LinkPtr) {
  1066.         if(reset[p]) {
  1067.             linkArray[s][counter] = 0.0;
  1068.         }
  1069.         dsum = actPrime * (LinkPtr->to->Out.output + 
  1070.                    (recurrentLinkWeight*linkArray[s][counter]));
  1071.         LN_CURRENT_SLOPE(LinkPtr) += change * dsum;
  1072.         linkArray[s][counter++] = dsum;
  1073.         }
  1074.  
  1075.         if(reset[p]) {
  1076.         linkArray[s][counter] = 0.0;
  1077.         }
  1078.         dsum = actPrime * (1 + (recurrentLinkWeight*linkArray[s][counter]));
  1079.         BIAS_CURRENT_SLOPE(SpecialUnitPtr) += change * dsum;
  1080.         linkArray[s][counter] = dsum;
  1081.     }
  1082.     }
  1083.     return(bestSpecialUnitScore);
  1084. }
  1085.  
  1086.  
  1087.  
  1088. /*****************************************************************************
  1089.   FUNCTION : rcc_QPS_updateNet
  1090.  
  1091.   PURPOSE  : Update the weights of the special units with quickprop.
  1092.   NOTES    :
  1093.  
  1094.   UPDATE   : 5.2.93
  1095. ******************************************************************************/
  1096. static void rcc_QPS_updateNet(float epsilon, float mu, float decay)
  1097. {
  1098.     struct Unit *SpecialUnitPtr;
  1099.     struct Link *LinkPtr;
  1100.     float shrinkFactor=mu/(mu+1);
  1101.     float bias_previousSlope,bias_currentSlope,bias_lastWeightChange,
  1102.           bias_weightChange;
  1103.     float ln_previousSlope,ln_currentSlope,ln_lastWeightChange,ln_weightChange;
  1104.     int o;
  1105.  
  1106.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,o) {
  1107.     bias_previousSlope = BIAS_PREVIOUS_SLOPE(SpecialUnitPtr);
  1108.     bias_currentSlope = BIAS_CURRENT_SLOPE(SpecialUnitPtr) + 
  1109.                         decay * SpecialUnitPtr->bias;
  1110.     bias_lastWeightChange = BIAS_LAST_WEIGHT_CHANGE(SpecialUnitPtr);
  1111.  
  1112.     bias_weightChange = 0.0;
  1113.  
  1114.     if(bias_previousSlope > 0.0) {
  1115.         if(bias_currentSlope > 0.0) {
  1116.         bias_weightChange -= epsilon * bias_currentSlope;
  1117.         }
  1118.         if(bias_currentSlope >= (shrinkFactor * bias_previousSlope)) {
  1119.         bias_weightChange += mu * bias_lastWeightChange;
  1120.         }else {
  1121.         bias_weightChange += (bias_lastWeightChange*bias_currentSlope)/ 
  1122.             (bias_previousSlope - bias_currentSlope); 
  1123.         }
  1124.     }else if(bias_previousSlope < 0.0) {
  1125.         if(bias_currentSlope < 0.0) {
  1126.         bias_weightChange -= epsilon * bias_currentSlope;
  1127.         }
  1128.         if(bias_currentSlope <= (shrinkFactor * bias_previousSlope)) {
  1129.         bias_weightChange += mu * bias_lastWeightChange;
  1130.         }else {
  1131.         bias_weightChange += (bias_lastWeightChange*bias_currentSlope)/ 
  1132.             (bias_previousSlope - bias_currentSlope); 
  1133.         }
  1134.     }else {
  1135.         bias_weightChange -= epsilon * bias_currentSlope;
  1136.     }
  1137.     SpecialUnitPtr->bias += 
  1138.         (BIAS_LAST_WEIGHT_CHANGE(SpecialUnitPtr) = bias_weightChange); 
  1139.     BIAS_PREVIOUS_SLOPE(SpecialUnitPtr) = bias_currentSlope;
  1140.     BIAS_CURRENT_SLOPE(SpecialUnitPtr) = 0.0;
  1141.  
  1142.     FOR_ALL_LINKS(SpecialUnitPtr,LinkPtr) {
  1143.    
  1144.         ln_weightChange = 0.0;
  1145.         ln_previousSlope = LN_PREVIOUS_SLOPE(LinkPtr);
  1146.         ln_currentSlope = LN_CURRENT_SLOPE(LinkPtr) + decay*LinkPtr->weight;
  1147.         ln_lastWeightChange = LN_LAST_WEIGHT_CHANGE(LinkPtr);
  1148.    
  1149.         if(ln_previousSlope > 0.0) {
  1150.         if(ln_currentSlope > 0.0) {
  1151.             ln_weightChange -= epsilon * ln_currentSlope;
  1152.         }
  1153.         if(ln_currentSlope >= (shrinkFactor * ln_previousSlope)) {
  1154.             ln_weightChange += mu * ln_lastWeightChange;
  1155.         }else {
  1156.             ln_weightChange += (ln_lastWeightChange * ln_currentSlope) / 
  1157.             (ln_previousSlope - ln_currentSlope); 
  1158.         }
  1159.         }else if(ln_previousSlope < 0.0) {
  1160.         if(ln_currentSlope < 0.0) {
  1161.             ln_weightChange -= epsilon * ln_currentSlope;
  1162.         }
  1163.         if(ln_currentSlope <= (shrinkFactor * ln_previousSlope)) {
  1164.             ln_weightChange += mu * ln_lastWeightChange;
  1165.         }else {
  1166.             ln_weightChange += (ln_lastWeightChange * ln_currentSlope) / 
  1167.             (ln_previousSlope - ln_currentSlope); 
  1168.         }
  1169.         }else {
  1170.         ln_weightChange -= epsilon * ln_currentSlope;
  1171.         }
  1172.    
  1173.         LinkPtr->weight += LN_LAST_WEIGHT_CHANGE(LinkPtr) = ln_weightChange; 
  1174.         LN_PREVIOUS_SLOPE(LinkPtr)   = ln_currentSlope;
  1175.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  1176.     }
  1177.     } 
  1178. }
  1179.  
  1180.  
  1181. /******************* end quickprop routines *************************/
  1182.  
  1183.  
  1184. /************* begin Backprop routines *********************/
  1185.  
  1186. /*****************************************************************************
  1187.   FUNCTION : rcc_BPO_trainNet
  1188.  
  1189.   PURPOSE  : Minimize the error of the output units.
  1190.   NOTES    :
  1191.  
  1192.   UPDATE   : 5.2.93
  1193. ******************************************************************************/
  1194. static void rcc_BPO_trainNet(int maxNoOfErrorUpdateCycles, float minErrorChange,
  1195.                              int outPatience, int StartPattern, int EndPattern, 
  1196.                  float eta, float mu, float fse, 
  1197.                  float **ParameterOutArray, int *NoOfOutParams)
  1198. {
  1199.     int m,p,counter=0;
  1200.     float oldNetError;
  1201.     static float OutParameter[1];
  1202.     float dummy=0.0;
  1203.     int start,end;
  1204.     int pat,sub;
  1205.  
  1206.     *NoOfOutParams = 1;
  1207.     *ParameterOutArray = OutParameter;
  1208.  
  1209.     SumSqError = 0.0;
  1210.     cc_initOutputUnits();
  1211.  
  1212.     /* compute the necessary sub patterns */
  1213.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  1214.     if(KernelErrorCode != KRERR_NO_ERROR)
  1215.         return;
  1216.  
  1217.     /* give oldNetError a meaningful initial value */
  1218.     NET_ERROR(OutParameter)=FLOAT_MAX;
  1219.     do {
  1220.     oldNetError = NET_ERROR(OutParameter);
  1221.     for(m=0;m<outPatience;m++) {
  1222.         NET_ERROR(OutParameter) = 0.0;
  1223.         SumSqError = 0.0;
  1224.         KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  1225.         start = kr_AbsPosOfFirstSubPat(StartPattern);
  1226.         end   = kr_AbsPosOfFirstSubPat(EndPattern);
  1227.         end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  1228.         for(p=start; p<=end;p++){
  1229.         kr_getSubPatternByNo(&pat,&sub,p);
  1230.         rcc_propagateNetForward(pat,sub);
  1231.         NET_ERROR(OutParameter) += 
  1232.             rcc_BPO_propagateNetBackward(pat,sub,fse);
  1233.         }
  1234.         rcc_BPO_updateNet(eta,mu,dummy);
  1235.         if(cc_printOnOff){
  1236.         printf("Epoch: %d NetError: %f \n",++counter,
  1237.                NET_ERROR(OutParameter));
  1238.         }
  1239.         if((maxNoOfErrorUpdateCycles--) == 0) {
  1240.         return;
  1241.         }
  1242.     }
  1243.     } while(fabs(oldNetError-NET_ERROR(OutParameter)) >= 
  1244.         (minErrorChange * oldNetError));
  1245. }
  1246.  
  1247.  
  1248.  
  1249. /*****************************************************************************
  1250.   FUNCTION : rcc_BPO_propagateNetBackward
  1251.  
  1252.   PURPOSE  : Calculate the error of the output units.
  1253.   NOTES    :
  1254.  
  1255.   UPDATE   : 5.2.93
  1256. ******************************************************************************/
  1257. static  float rcc_BPO_propagateNetBackward(int PatternNo, int sub_pat_no,
  1258.                        float fse)
  1259. {
  1260.     struct Link   *LinkPtr;
  1261.     struct Site   *site_ptr;
  1262.     struct Unit   *OutputUnitPtr;
  1263.     Patterns      out_pat;
  1264.     float         error,sum_error,devit;
  1265.     int dummy=0.0;
  1266.  
  1267.     sum_error = 0.0;    
  1268.     out_pat = kr_getSubPatData(PatternNo,sub_pat_no,OUTPUT,NULL);
  1269.  
  1270.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
  1271.     devit =  OutputUnitPtr->Out.output - *(out_pat++);
  1272.  
  1273.     sum_error += devit * devit;
  1274.     error = devit * ((*OutputUnitPtr->act_deriv_func)(OutputUnitPtr) + fse);
  1275.     SumSqError += error * error;
  1276.  
  1277.     BIAS_CURRENT_SLOPE(OutputUnitPtr) += error;
  1278.  
  1279.     if (UNIT_HAS_DIRECT_INPUTS(OutputUnitPtr)) {  
  1280.         FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  1281.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  1282.         }
  1283.     }else {
  1284.         FOR_ALL_SITES_AND_LINKS(OutputUnitPtr,site_ptr,LinkPtr) {
  1285.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  1286.         }
  1287.     }
  1288.     }
  1289.     return(sum_error); 
  1290. }
  1291.  
  1292.  
  1293.  
  1294. /*****************************************************************************
  1295.   FUNCTION : rcc_BPO_updateNet
  1296.  
  1297.   PURPOSE  : Update the weights of the output units with backprop.
  1298.   NOTES    :
  1299.  
  1300.   UPDATE   : 5.2.93
  1301. ******************************************************************************/
  1302. static void rcc_BPO_updateNet(float eta, float mu, float dummy)
  1303. {
  1304.     struct Unit *outputUnitPtr;
  1305.     struct Link *LinkPtr;
  1306.     float bias_weightChange;
  1307.     float ln_weightChange;
  1308.     int s;
  1309.  
  1310.     FOR_ALL_OUTPUT_UNITS(outputUnitPtr,s) {
  1311.     bias_weightChange = BIAS_CURRENT_SLOPE(outputUnitPtr) * eta + 
  1312.                         BIAS_PREVIOUS_SLOPE(outputUnitPtr) * mu;
  1313.     outputUnitPtr->bias -= bias_weightChange; 
  1314.     BIAS_PREVIOUS_SLOPE(outputUnitPtr) = BIAS_CURRENT_SLOPE(outputUnitPtr);
  1315.     BIAS_CURRENT_SLOPE(outputUnitPtr) = 0.0;
  1316.  
  1317.     FOR_ALL_LINKS(outputUnitPtr,LinkPtr) {
  1318.         ln_weightChange = LN_CURRENT_SLOPE(LinkPtr) * eta + 
  1319.                       LN_PREVIOUS_SLOPE(outputUnitPtr) * mu;
  1320.         LinkPtr->weight -= ln_weightChange; 
  1321.         LN_PREVIOUS_SLOPE(outputUnitPtr) = LN_CURRENT_SLOPE(outputUnitPtr);
  1322.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  1323.     }
  1324.     }
  1325. }
  1326.  
  1327.  
  1328.  
  1329. /*****************************************************************************
  1330.   FUNCTION : rcc_BPS_trainNet
  1331.  
  1332.   PURPOSE  : Maximize the covariance between the special units and the 
  1333.              output units.
  1334.   NOTES    :
  1335.  
  1336.   UPDATE   : 5.2.93
  1337. ******************************************************************************/
  1338. static void rcc_BPS_trainNet(int maxNoOfCovarianceUpdateCycles, 
  1339.                  float minCovarianceChange, int specialPatience, 
  1340.                  int StartPattern, int EndPattern, float eta, 
  1341.                  float mu, float dummy1, int MaxSpecialUnitNo)
  1342. {
  1343.     int m,counter=0;
  1344.     float oldHighScore,newHighScore=0.0;
  1345.  
  1346.     cc_initErrorArrays();
  1347.     rcc_calculateOutputUnitError(StartPattern,EndPattern);
  1348.  
  1349.     do {
  1350.     oldHighScore = newHighScore;
  1351.     for(m=0;m<specialPatience;m++) { 
  1352.         counter++;
  1353.         rcc_calculateSpecialUnitActivation(StartPattern,EndPattern);
  1354.         newHighScore = rcc_BPS_propagateNetBackward(StartPattern,EndPattern,
  1355.                             counter);
  1356.         rcc_BPS_updateNet(eta,mu,dummy1);
  1357.         cc_initActivationArrays(); 
  1358.         if((maxNoOfCovarianceUpdateCycles--) == 0) {
  1359.         return;
  1360.         }    
  1361.     }
  1362.     } while(fabs(newHighScore-oldHighScore) >= 
  1363.         (minCovarianceChange * oldHighScore));
  1364. }
  1365.  
  1366.  
  1367.  
  1368. /*****************************************************************************
  1369.   FUNCTION : rcc_BPS_propagateNetBackward
  1370.  
  1371.   PURPOSE  : Calculate the special unit with the maximum covariance and return 
  1372.              it.
  1373.   NOTES    :
  1374.  
  1375.   UPDATE   : 5.2.93
  1376. ******************************************************************************/
  1377. static float rcc_BPS_propagateNetBackward(int StartPattern, int EndPattern, 
  1378.                       int counter)
  1379. {
  1380.     float change=0.0,bestSpecialUnitScore,actPrime,recurrentLinkWeight,dsum;
  1381.     int s,o,p,n,h;
  1382.     struct Unit *SpecialUnitPtr,*OutputUnitPtr,*hiddenUnitPtr;
  1383.     struct Link *LinkPtr,*recurrentLinkPtr;
  1384.     int start,end;
  1385.  
  1386.     bestSpecialUnitScore = 
  1387.     cc_calculateCorrelation(StartPattern,EndPattern,counter); 
  1388.  
  1389.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  1390.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  1391.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  1392.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  1393.     n = end - start +1;
  1394.     for(p=start; p<=end;p++){
  1395.  
  1396.     cc_initInputUnitsWithPattern(p);
  1397.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,h) { 
  1398.         hiddenUnitPtr->lln = reset[p];
  1399.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func)(hiddenUnitPtr);
  1400.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  1401.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  1402.         }else {
  1403.         hiddenUnitPtr->Out.output = 
  1404.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  1405.         }
  1406.     }
  1407.    
  1408.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
  1409.         change = 0.0;
  1410.         SpecialUnitPtr->act = SpecialUnitAct[p][s];
  1411.         actPrime = (*SpecialUnitPtr->act_deriv_func)(SpecialUnitPtr);
  1412.         FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  1413.         change -= CorBetweenSpecialActAndOutError[s][o] *
  1414.            ((OutputUnitError[p][o]-OutputUnitSumError[o]/n)/SumSqError);
  1415.         }
  1416.  
  1417.         counter = 0;
  1418.         GET_RECURRENT_LINK(SpecialUnitPtr,recurrentLinkPtr);
  1419.         if(reset[p]) {
  1420.         linkArray[s][counter] = 0.0;
  1421.         }
  1422.         recurrentLinkWeight = recurrentLinkPtr->weight; 
  1423.         if(!reset[p]) {    /* calculate slope of the recurrent link */
  1424.         dsum = actPrime * (SpecialUnitAct[p-1][s] + 
  1425.                    (recurrentLinkWeight*linkArray[s][counter]));
  1426.         LN_CURRENT_SLOPE(recurrentLinkPtr) += change * dsum;
  1427.         linkArray[s][counter++] = dsum; 
  1428.         }
  1429.  
  1430.         FOR_ALL_NOT_RECURRENT_LINKS(SpecialUnitPtr,LinkPtr) {
  1431.         if(reset[p]) {
  1432.             linkArray[s][counter] = 0.0;
  1433.         }
  1434.         dsum = actPrime * (LinkPtr->to->Out.output + 
  1435.                    (recurrentLinkWeight*linkArray[s][counter]));
  1436.         LN_CURRENT_SLOPE(LinkPtr) += change * dsum;
  1437.         linkArray[s][counter++] = dsum;
  1438.         }
  1439.  
  1440.         if(reset[p]) {
  1441.         linkArray[s][counter] = 0.0;
  1442.         }
  1443.         dsum = actPrime * (1 + (recurrentLinkWeight*linkArray[s][counter]));
  1444.         BIAS_CURRENT_SLOPE(SpecialUnitPtr) += change * dsum;
  1445.         linkArray[s][counter] = dsum;
  1446.     }
  1447.     }
  1448.     return(bestSpecialUnitScore);
  1449. }
  1450.  
  1451.  
  1452.  
  1453. /*****************************************************************************
  1454.   FUNCTION : rcc_BPS_updateNet
  1455.  
  1456.   PURPOSE  : Update the weights of the special units with backprop.
  1457.   NOTES    :
  1458.  
  1459.   UPDATE   : 5.2.93
  1460. ******************************************************************************/
  1461. static void rcc_BPS_updateNet(float eta, float mu, float dummy)
  1462. {
  1463.     struct Unit *specialUnitPtr;
  1464.     struct Link *LinkPtr;
  1465.     float bias_weightChange;
  1466.     float ln_weightChange;
  1467.     int s;
  1468.  
  1469.     FOR_ALL_SPECIAL_UNITS(specialUnitPtr,s) {
  1470.     bias_weightChange = BIAS_CURRENT_SLOPE(specialUnitPtr) * eta + 
  1471.                         BIAS_PREVIOUS_SLOPE(specialUnitPtr) * mu;
  1472.     specialUnitPtr->bias -= bias_weightChange; 
  1473.     BIAS_PREVIOUS_SLOPE(specialUnitPtr) =BIAS_CURRENT_SLOPE(specialUnitPtr);
  1474.     BIAS_CURRENT_SLOPE(specialUnitPtr) = 0.0;
  1475.  
  1476.     FOR_ALL_LINKS(specialUnitPtr,LinkPtr) {
  1477.         ln_weightChange = LN_CURRENT_SLOPE(LinkPtr) * eta + 
  1478.                       LN_PREVIOUS_SLOPE(specialUnitPtr) * mu;
  1479.         LinkPtr->weight -= ln_weightChange; 
  1480.         LN_PREVIOUS_SLOPE(specialUnitPtr) =LN_CURRENT_SLOPE(specialUnitPtr);
  1481.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  1482.     }
  1483.     }
  1484. }
  1485.  
  1486.  
  1487. /******************* end packprop routines *************************/
  1488.  
  1489.  
  1490.  
  1491. /*****************************************************************************
  1492.   FUNCTION : rcc_generateSpecialUnits
  1493.  
  1494.   PURPOSE  : Generates the special units.
  1495.   NOTES    :
  1496.  
  1497.   UPDATE   : 5.2.93
  1498. ******************************************************************************/
  1499. static krui_err rcc_generateSpecialUnits(int MaxSpecialUnitNo, int OutputXMax, 
  1500.                      int type)
  1501. {
  1502.     int i,selector;
  1503.     struct Unit *UnitPtr;
  1504.     int CurrentUnit;
  1505.  
  1506.     for(i=0;i<MaxSpecialUnitNo;i++) {
  1507.     if(type==RANDOM){
  1508.         selector = i % (NO_OF_ACT_FUNCS - 1);
  1509.     }else {
  1510.         selector = type;
  1511.     }
  1512.     KernelErrorCode = 
  1513.         kr_unitSetTType(CurrentUnit=kr_makeDefaultUnit(),SPECIAL); 
  1514.     ERROR_CHECK;
  1515.  
  1516.     KernelErrorCode = 
  1517.         krui_setUnitActFunc(CurrentUnit,rcc_actFuncArray[selector]);
  1518.     ERROR_CHECK;  
  1519.  
  1520.     UnitPtr = kr_getUnitPtr(CurrentUnit); 
  1521.     ERROR_CHECK;
  1522.  
  1523.     SET_UNIT_XPOS(UnitPtr,OutputXMax+3);
  1524.     SET_UNIT_YPOS(UnitPtr,2+i);
  1525.     KernelErrorCode = krui_setCurrentUnit(CurrentUnit); 
  1526.     ERROR_CHECK;
  1527.  
  1528.     /* links between special units and input units */
  1529.     FOR_ALL_UNITS(UnitPtr){
  1530.         if((IS_INPUT_UNIT(UnitPtr) || IS_HIDDEN_UNIT(UnitPtr)) && 
  1531.            UNIT_IN_USE(UnitPtr)) {
  1532.         KernelErrorCode = 
  1533.             krui_createLink(GET_UNIT_NO(UnitPtr),
  1534.                     cc_generateRandomNo(RCC_MAX_VALUE)); 
  1535.         ERROR_CHECK;
  1536.         }
  1537.     }
  1538.     KernelErrorCode = krui_createLink(CurrentUnit,
  1539.                       cc_generateRandomNo(RCC_MAX_VALUE));
  1540.     ERROR_CHECK;
  1541.     }  
  1542.     return(KRERR_NO_ERROR);
  1543. }
  1544.  
  1545.  
  1546.  
  1547. /*****************************************************************************
  1548.   FUNCTION : rcc_generateHiddenUnit 
  1549.  
  1550.   PURPOSE  : Generates the hidden units.
  1551.   NOTES    :
  1552.  
  1553.   UPDATE   : 5.2.93
  1554. ******************************************************************************/
  1555. static krui_err rcc_generateHiddenUnit(int maxYPosOfHiddenUnit, 
  1556.                        int *xPosOfLastInsertedHiddenUnit,
  1557.                                        int *yPosOfLastInsertedHiddenUnit)
  1558. {
  1559.     int CurrentUnit,dummy,NewHiddenUnit,s;
  1560.     struct Unit *HiddenUnitPtr,*SpecialUnitPtr,*OutputUnitPtr;
  1561.     FlintType linkValue=0.0;
  1562.  
  1563.  
  1564.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s){
  1565.     KernelErrorCode = 
  1566.         krui_setCurrentUnit(CurrentUnit = GET_UNIT_NO(SpecialUnitPtr)); 
  1567.     ERROR_CHECK;
  1568.  
  1569.     if(krui_isConnected(CurrentUnit)) {
  1570.         if(SpecialUnitPtr == bestSpecialUnitPtr) {
  1571.         linkValue = ((struct Link *)(SpecialUnitPtr->sites))->weight;
  1572.         }
  1573.         KernelErrorCode = krui_deleteLink(); /* delete recurent link */
  1574.         ERROR_CHECK;
  1575.     }else {
  1576.         KernelErrorCode = KRERR_CC_ERROR5;
  1577.         ERROR_CHECK;
  1578.     } 
  1579.     }
  1580.  
  1581.     CurrentUnit = 
  1582.     KernelErrorCode = 
  1583.         kr_copyUnit(ONLY_INPUTS,GET_UNIT_NO(bestSpecialUnitPtr));
  1584.     if(KernelErrorCode < 0) {
  1585.     ERROR_CHECK;
  1586.     }
  1587.     KernelErrorCode = KRERR_NO_ERROR;
  1588.  
  1589.     KernelErrorCode = kr_unitSetTType(CurrentUnit,HIDDEN); 
  1590.     ERROR_CHECK;
  1591.  
  1592.     HiddenUnitPtr = kr_getUnitPtr(CurrentUnit); 
  1593.     ERROR_CHECK;
  1594.  
  1595.     KernelErrorCode = 
  1596.     cc_setHiddenUnit(HiddenUnitPtr,maxYPosOfHiddenUnit,
  1597.              xPosOfLastInsertedHiddenUnit,
  1598.              yPosOfLastInsertedHiddenUnit);
  1599.     ERROR_CHECK;
  1600.  
  1601.     KernelErrorCode = krui_setCurrentUnit(CurrentUnit); 
  1602.     ERROR_CHECK;
  1603.  
  1604.     /* generate recurent link */
  1605.     KernelErrorCode = krui_createLink(CurrentUnit,linkValue); 
  1606.     ERROR_CHECK;
  1607.  
  1608.     NewHiddenUnit = CurrentUnit;
  1609.     /* generate Links between output unit and new hidden unit */
  1610.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
  1611.     CurrentUnit = GET_UNIT_NO(OutputUnitPtr);
  1612.     KernelErrorCode = krui_setCurrentUnit(CurrentUnit); 
  1613.     ERROR_CHECK;
  1614.  
  1615.     KernelErrorCode = krui_createLink(NewHiddenUnit,0.0); 
  1616.     ERROR_CHECK;
  1617.     }
  1618.  
  1619.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s){
  1620.     KernelErrorCode = 
  1621.         krui_setCurrentUnit(CurrentUnit = GET_UNIT_NO(SpecialUnitPtr)); 
  1622.     ERROR_CHECK;
  1623.     
  1624.     KernelErrorCode = 
  1625.         krui_createLink(NewHiddenUnit,cc_generateRandomNo(RCC_MAX_VALUE));
  1626.     ERROR_CHECK;
  1627.  
  1628.     /* generate recurent link */
  1629.     KernelErrorCode = 
  1630.         krui_createLink(CurrentUnit,cc_generateRandomNo(RCC_MAX_VALUE)); 
  1631.     ERROR_CHECK;
  1632.     }
  1633.  
  1634.     KernelErrorCode = kr_topoSort(TOPOLOGICAL_RCC);
  1635.     ERROR_CHECK;    
  1636.  
  1637.     if(CC_TEST) {
  1638.     cc_printUnitArray();
  1639.     cc_printTopoPtrArray();
  1640.     }
  1641.  
  1642.     KernelErrorCode = cc_setPointers();
  1643.     ERROR_CHECK;
  1644.  
  1645.     NetModified = FALSE;
  1646.     return(KRERR_NO_ERROR);
  1647. }
  1648.  
  1649.  
  1650.  
  1651. /*****************************************************************************
  1652.   FUNCTION : LEARN_RecCasCor 
  1653.  
  1654.   PURPOSE  : The main routine of RCC
  1655.   NOTES    :
  1656.  
  1657.   UPDATE   : 5.2.93
  1658. ******************************************************************************/
  1659. krui_err LEARN_RecCasCor(int StartPattern, int EndPattern, 
  1660.              float *ParameterInArray, int NoOfInParams, 
  1661.              float **ParameterOutArray, int *NoOfOutParams)
  1662. {
  1663.     static int   OldMaxSpecialUnitNo=0,MaxSpecialUnitNo;
  1664.     static int   maxNoOfErrorUpdateCycles,maxNoOfCovarianceUpdateCycles,
  1665.                  outPatience,specialPatience;
  1666.     static int   maxYPosOfHiddenUnit,xPosOfLastInsertedHiddenUnit,
  1667.                  yPosOfLastInsertedHiddenUnit;
  1668.     static int   specialFuncType,oldSpecialFuncType,outputXMax,learnFunc;
  1669.     static float maxPixelError,minErrorChange,minCovarianceChange,
  1670.                  param1,param2,param3,param4,param5,param6;
  1671.   
  1672.     srand48((long)time((long *)0)); 
  1673.  
  1674.     if(strcmp(krui_getUpdateFunc(),"RCC_Order")){
  1675.     return(KRERR_CC_ERROR10);
  1676.     }
  1677.  
  1678.     /* Enter this path only  if "ALL" in the remote pannel was pressed */
  1679.     if(cc_allButtonIsPressed == 1) { 
  1680.  
  1681.     param1 = ParameterInArray[0];
  1682.     param2 = ParameterInArray[1];
  1683.     param3 = ParameterInArray[2];
  1684.  
  1685.     param4 = ParameterInArray[3];
  1686.     param5 = ParameterInArray[4];
  1687.     param6 = 0.001;
  1688.     /*  param6 = ParameterInArray[5]; */
  1689.   
  1690.     /* cc_data.GLOBAL.pixelError */
  1691.     maxPixelError = ParameterInArray[6];
  1692.  
  1693.     /* cc_data.GLOBAL.learningFunc */
  1694.     learnFunc     = (int)ParameterInArray[7]; 
  1695.  
  1696.     /* cc_data.GLOBAL.onOff */ 
  1697.     cc_printOnOff = (int)ParameterInArray[8]; 
  1698.  
  1699.     /* cc_data.CAND.covarianceChange */
  1700.     minCovarianceChange = ParameterInArray[9];
  1701.  
  1702.     /* cc_data.CAND.candidatePatience */ 
  1703.     specialPatience = ParameterInArray[10]; 
  1704.  
  1705.     /* cc_data.CAND.maxNoOfUpdateCycles */
  1706.     maxNoOfCovarianceUpdateCycles = ParameterInArray[11]; 
  1707.  
  1708.     /* cc_data.CAND.maxNoOfCandUnits */
  1709.     MaxSpecialUnitNo = ParameterInArray[12]; 
  1710.  
  1711.     /* cc_data.CAND.actFunc */
  1712.     specialFuncType = (int)ParameterInArray[13]; 
  1713.         
  1714.     /* cc_data.OUT.errorChange */
  1715.     minErrorChange = ParameterInArray[14];
  1716.  
  1717.     /* cc_data.OUT.outputPatience */ 
  1718.     outPatience = ParameterInArray[15]; 
  1719.  
  1720.     /* cc_data.OUT.maxNoOfUpdateCycles */
  1721.     maxNoOfErrorUpdateCycles = ParameterInArray[16]; 
  1722.  
  1723.     cc_end = 0;
  1724.     cc_cascade = 1;
  1725.  
  1726.     cc_compareActFunctions(specialFuncType,RCC);
  1727.     rcc_manageResetArray(StartPattern,EndPattern,1);
  1728.     rcc_manageLinkArray(MaxSpecialUnitNo,1);
  1729.  
  1730.     switch(learnFunc) {
  1731.       case BACKPROP:
  1732.         cc_trainOutputUnits  = rcc_BPO_trainNet;
  1733.         cc_trainSpecialUnits = rcc_BPS_trainNet; 
  1734.         break;
  1735.       case QUICKPROP:
  1736.         cc_trainOutputUnits  = rcc_QPO_trainNet;
  1737.         cc_trainSpecialUnits = rcc_QPS_trainNet;
  1738.         break;
  1739.       case RPROP: 
  1740.         cc_trainOutputUnits  = rcc_RPO_trainNet;
  1741.         cc_trainSpecialUnits = rcc_RPS_trainNet; 
  1742.         break;
  1743.       default: CC_ERROR(KRERR_CC_ERROR3);
  1744.     }
  1745.  
  1746.     maxYPosOfHiddenUnit =
  1747.         xPosOfLastInsertedHiddenUnit =
  1748.         yPosOfLastInsertedHiddenUnit =
  1749.             outputXMax=0;
  1750.     KernelErrorCode = 
  1751.         cc_calculateNetParameters(&maxYPosOfHiddenUnit,
  1752.                       &xPosOfLastInsertedHiddenUnit,
  1753.                       &yPosOfLastInsertedHiddenUnit,
  1754.                       &outputXMax);
  1755.     ERROR_CHECK;
  1756.     }
  1757.  
  1758.     if(cc_printOnOff){
  1759.     if(strcmp(krui_getUpdateFunc(),"RCC_Order")){
  1760.         return(KRERR_CC_ERROR10);
  1761.     }
  1762.     if(strcmp(krui_getInitialisationFunc(),"RCC_Weights")){
  1763.         return(KRERR_CC_ERROR11);
  1764.     }    
  1765.     }
  1766.  
  1767.  
  1768.   
  1769.     if(cc_end){
  1770.     return(KRERR_NO_ERROR);
  1771.     }
  1772.  
  1773.     if(NetModified || (TopoSortID!=TOPOLOGICAL_RCC) || 
  1774.        (LearnFuncHasChanged) || (OldMaxSpecialUnitNo!=MaxSpecialUnitNo) || 
  1775.        (cc_update)) {
  1776.  
  1777.     OldMaxSpecialUnitNo = MaxSpecialUnitNo;
  1778.     oldSpecialFuncType  = specialFuncType;
  1779.  
  1780.     KernelErrorCode = rcc_searchRecurrentLinks();
  1781.     ERROR_CHECK;
  1782.  
  1783.     KernelErrorCode = cc_deleteAllSpecialUnits();
  1784.     ERROR_CHECK; 
  1785.  
  1786.     KernelErrorCode = rcc_generateSpecialUnits(MaxSpecialUnitNo,outputXMax,
  1787.                            specialFuncType);
  1788.     ERROR_CHECK;
  1789.  
  1790.     KernelErrorCode = kr_topoSort(TOPOLOGICAL_RCC);
  1791.     ERROR_CHECK;    
  1792.  
  1793.     if(CC_TEST) {
  1794.         cc_printUnitArray();
  1795.         cc_printTopoPtrArray();
  1796.     }
  1797.  
  1798.     KernelErrorCode = cc_setPointers();
  1799.     ERROR_CHECK;
  1800.  
  1801.     cc_update = 0;
  1802.     LearnFuncHasChanged = 0;
  1803.     NetModified = 0;
  1804.     }
  1805.  
  1806.     if(cc_allButtonIsPressed == 1) {
  1807.     KernelErrorCode = cc_freeStorage(StartPattern,EndPattern,0);
  1808.     ERROR_CHECK;
  1809.  
  1810.     KernelErrorCode = 
  1811.         cc_allocateStorage(StartPattern,EndPattern,MaxSpecialUnitNo);
  1812.     ERROR_CHECK;
  1813.     }
  1814.  
  1815.     if(oldSpecialFuncType != specialFuncType){
  1816.     oldSpecialFuncType = specialFuncType;
  1817.     cc_changeActFuncOfSpecialUnits(specialFuncType,RCC);
  1818.     }
  1819.  
  1820.     KernelErrorCode = cc_initSpecialUnitLinks();
  1821.     ERROR_CHECK;
  1822.  
  1823.     /* For safety, this error should only appear, if someone has changed 
  1824.        the program in a wrong way!!!
  1825.        */
  1826.     if(cc_storageFree){ 
  1827.     CC_ERROR(KRERR_CC_ERROR2);    
  1828.     }
  1829.     if(cc_allButtonIsPressed == 1) {
  1830.     cc_allButtonIsPressed = 0;
  1831.     if((outPatience != 0) && (maxNoOfErrorUpdateCycles != 0)) {
  1832.         (*cc_trainOutputUnits)(maxNoOfErrorUpdateCycles,minErrorChange,
  1833.                    outPatience,StartPattern,EndPattern,param1,
  1834.                    param2,param3,ParameterOutArray,
  1835.                    NoOfOutParams);
  1836.     }
  1837.     }
  1838.  
  1839.     if(rcc_test(StartPattern,EndPattern,maxPixelError) ==  CONTINUE_LEARNING) {
  1840.     if((specialPatience != 0) && (maxNoOfCovarianceUpdateCycles != 0)) {
  1841.         (*cc_trainSpecialUnits)(maxNoOfCovarianceUpdateCycles,
  1842.                     minCovarianceChange,specialPatience,
  1843.                     StartPattern,EndPattern,param4,
  1844.                     param5,param6,MaxSpecialUnitNo);
  1845.     }
  1846.     }else {            /* Stop learning */
  1847.     cc_end = 1;
  1848.     return(KRERR_NO_ERROR);
  1849.     }
  1850.  
  1851.     if((specialPatience != 0) && (maxNoOfCovarianceUpdateCycles != 0)) {
  1852.     KernelErrorCode = 
  1853.         rcc_generateHiddenUnit(maxYPosOfHiddenUnit,
  1854.                    &xPosOfLastInsertedHiddenUnit,
  1855.                    &yPosOfLastInsertedHiddenUnit);
  1856.     ERROR_CHECK;
  1857.     }
  1858.  
  1859.     if((outPatience != 0) && (maxNoOfErrorUpdateCycles != 0)) {
  1860.     (*cc_trainOutputUnits)(maxNoOfErrorUpdateCycles,minErrorChange,
  1861.                    outPatience,StartPattern,EndPattern,param1,
  1862.                    param2,param3,ParameterOutArray,NoOfOutParams); 
  1863.     }
  1864.     return(KRERR_NO_ERROR);
  1865. }
  1866.  
  1867.  
  1868.  
  1869.